﻿// Original author contact info: Owen Emlen (owene_1998@yahoo.com)
// Note: other individuals may also have contributed to this code
// Project hosted on CodePlex.com as of 1/10/2009 at http://wpfimageviewer.codeplex.com
using System;
using System.Collections.ObjectModel;
using BrainTechLLC.ImageOperators;
using System.ComponentModel;
using System.Linq;
using System.Windows;
using System.Windows.Input;
using System.Windows.Threading;
using BrainTechLLC;
using CPPClassLibrary;
using DirectoryViewModels;
using ImageAppDataModels;
using ImageAppViewModels;
using System.IO;
using System.Collections.Generic;
using System.Text;
using BrainTechLLC.ThreadSafeObjects;
using System.Drawing;
using System.Windows.Media;
using System.Reflection;
using System.Threading;
using System.Diagnostics;

namespace WpfImageDuplicates
{
    public class CountClass
    {
        public object _lock = new object();
        public Dictionary<object, int> Counts = new Dictionary<object, int>();
        public Dictionary<object, long> ByteCounts = new Dictionary<object, long>();
        public ThreadSafeLookup<object, object> Seen = new ThreadSafeLookup<object, object>();

        public void Increment(object o, long bytes)
        {
            lock (_lock)
            {
                int val;
                if (!Counts.TryGetValue(o, out val))
                {
                    Counts.Add(o, 1);
                }
                else
                {
                    Counts[o] = val + 1;
                }

                long val2;
                if (!ByteCounts.TryGetValue(o, out val2))
                {
                    ByteCounts.Add(o, bytes);
                }
                else
                {
                    ByteCounts[o] = val2 + bytes;
                }
            }
        }

        public void AddCount(Bitmap vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            try
            {
                long bytesTaken = vm.GetByteEstimate();
                Increment("Bitmaps", bytesTaken);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        public void AddCountTransformedBitmap(FileImage fi, Bitmap vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            try
            {
                long bytesTaken = vm.GetByteEstimate(fi._transformedWidth, fi._transformedHeight, vm.PixelFormat);
                Increment("TransformedBitmaps", bytesTaken);
            }
            catch (Exception ex)
            {
                Console.WriteLine(ex.ToString());
            }
        }

        public void AddCount(byte[] vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            string prop = string.Empty;
            Increment("ImageBytesCached", vm.LongLength);
        }

        public void AddCount(ThumbnailView vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            Increment("ThumbnailView", 0);
        }

        public void AddCountThumbImageSource(ImageSource vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            Increment("ThumbImageSourcesCached", vm.EstimateImageSourceBytesUsed());
        }

        public void AddCount(ImageSource vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            Increment("ImageSource", vm.EstimateImageSourceBytesUsed());
        }

        public void AddCountThumbnail(Bitmap vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            long bytesTaken = vm.GetByteEstimate();
            Increment("ThumbsLoaded", bytesTaken);
        }

        public void AddCount(FileImage vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            if (vm.BitmapLoaded)
            {
                AddCount(vm.BitmapCached);
            }
            if (vm.ImageBytesCached != null)
            {
                AddCount(vm.ImageBytesCached);
            }
            if (vm.ImageSourceCached != null)
            {
                AddCount(vm.ImageSourceCached);
            }
            if (vm.ThumbnailCached != null)
            {
                AddCountThumbnail(vm.ThumbnailCached);
            }
            if (vm.TransformedBitmapCached != null)
            {
                AddCountTransformedBitmap(vm, vm.TransformedBitmapCached);
            }
        }

        public void AddCount(IFileImage vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            if (vm.BitmapLoaded)
            {
                AddCount(vm.BitmapCached);
            }
            if (vm.ImageBytesCached != null)
            {
                AddCount(vm.ImageBytesCached);
            }
            if (vm.ImageSourceCached != null)
            {
                AddCount(vm.ImageSourceCached);
            }
            if (vm.ThumbnailCached != null)
            {
                AddCountThumbnail(vm.ThumbnailCached);
            }
            var fi = vm as FileImage;
            if (fi != null && fi.TransformedBitmapCached != null)
            {
                AddCountTransformedBitmap(fi, fi.TransformedBitmapCached);
            }
        }

        public void AddCount(FileImageViewModel vm)
        {
            if (vm == null || Seen[vm] != null)
                return;

            Seen.Add(vm, vm);

            string prop = string.Empty;
            if (vm.BitmapLoaded)
            {
                AddCount(vm.Item.Bitmap);
            }
            if (vm.Item.ImageBytesCached != null)
            {
                AddCount(vm.Item.ImageBytesCached);
            }
            if (vm.Item.ImageSourceCached != null)
            {
                AddCount(vm.Item.ImageSourceCached);
            }
            if (vm.ThumbImageSourceCached != null)
            {
                AddCountThumbImageSource(vm.ThumbImageSourceCached);
            }
            if (vm.ThumbLoaded)
            {
                AddCountThumbnail(vm.Item.ThumbnailCached);
            }
            var fi = vm.FileImage as FileImage;
            if (fi.TransformedBitmapCached != null)
            {
                AddCountTransformedBitmap(fi, fi.TransformedBitmapCached);
            }
        }

        public override string ToString()
        {
            StringBuilder sb = new StringBuilder();
            foreach (var kvp in Counts)
            {
                long bytes = 0;
                ByteCounts.TryGetValue(kvp.Key, out bytes);
                sb.AppendLine(string.Format("Count for {0}: {1}, Bytes: {2}KB", kvp.Key, kvp.Value.ToString(), bytes / 1024));
            }
            sb.AppendLine(string.Format("Threads: {0}", Process.GetCurrentProcess().Threads.Count));
            return sb.ToString();
        }
    }
}
